48장. ECS Service Discovery — Cloud Map
이 장에서 말하고자 하는 것
ALB는 외부 트래픽을 분배해준다.
그런데 컨테이너끼리 서로 부를 때는 어떻게 할까?
orders 컨테이너 → users 컨테이너 호출
이때 매번 새 Task의 IP를 알아내기는 어렵다.
이 문제를 푸는 게
AWS Cloud Map
이고 ECS에서 이걸 활용하는 기능이
ECS Service Discovery
다.
1. 무엇을 해결하는가
ECS Task는 IP가 자주 바뀐다.
users-task-1 : 10.0.1.10
users-task-2 : 10.0.2.11
... 죽고 살고 ...
users-task-3 : 10.0.1.45
대신 Service에 이름을 붙이면
users.local
이 이름이 자동으로 현재 살아 있는 Task의 IP들을 가리킨다.
다른 컨테이너는
http://users.local:8080으로 부르기만 하면 된다
2. 동작 구조
[ECS Service "users"]
├─ task 1 (10.0.1.10)
└─ task 2 (10.0.2.11)
↓ 자동 등록
[Cloud Map: users.local]
├─ A 10.0.1.10
└─ A 10.0.2.11
↓ DNS 질의
[orders 컨테이너] → users.local 으로 요청
Task가 뜨고 죽을 때마다 Cloud Map의 DNS가 자동으로 갱신된다
3. ALB와 Service Discovery는 자리가 다르다
ALB → 외부 사용자 → 서비스
Service Discovery → 서비스 ↔ 서비스 (내부)
- ALB: L7 라우팅, 인증서, 헬스 체크 정밀
- Service Discovery: 단순 DNS, 내부 식별
내부 호출에 ALB를 또 두면
- 비용이 든다
- 지연이 늘어난다
- 트래픽이 굳이 외부 경로를 흉내 낸다
내부 호출은 Service Discovery로.
4. Service Connect — 더 단단한 옵션
ECS는 Service Connect 라는 진화된 방식도 제공한다.
- DNS 기반 + 사이드카 프록시
- 자동 재시도 · 타임아웃 · 메트릭
- HTTP/2 · gRPC 지원
새로 시작하는 프로젝트라면 Service Connect 부터 검토해도 좋다.
5. 우리 서비스에서
[ALB] ← 외부 트래픽
↓
[ECS Service: web]
↓ http://users.local
[ECS Service: users]
↓ http://payments.local
[ECS Service: payments]
- 외부 → 내부: ALB
- 내부 → 내부: Service Discovery (또는 Service Connect)
6. 직접 확인해보기 — CLI
aws servicediscovery create-private-dns-namespace \
--name local \
--vpc <vpc-id>
aws servicediscovery create-service \
--name users \
--dns-config "NamespaceId=<ns-id>,DnsRecords=[{Type=A,TTL=10}]"
dig users.local
VPC 안에서만 응답한다.
7. 코드로는 이렇게 생겼다 — Terraform
resource "aws_service_discovery_private_dns_namespace" "main" {
name = "local"
vpc = aws_vpc.main.id
}
resource "aws_service_discovery_service" "users" {
name = "users"
dns_config {
namespace_id = aws_service_discovery_private_dns_namespace.main.id
dns_records {
type = "A"
ttl = 10
}
}
}
resource "aws_ecs_service" "users" {
name = "users"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.users.arn
desired_count = 2
launch_type = "FARGATE"
network_configuration {
subnets = [aws_subnet.private_a.id, aws_subnet.private_b.id]
security_groups = [aws_security_group.task.id]
}
service_registries {
registry_arn = aws_service_discovery_service.users.arn
}
}
service_registries 한 줄이
ECS Service와 Cloud Map을 묶는다.
8. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. 내부 호출에도 ALB를 둔다
비용 · 지연 · 복잡도 모두 늘어난다.
안티패턴 2. DNS TTL을 길게 둔다
Task가 죽었는데 클라이언트가 옛 IP로 계속 보낸다.
내부 Discovery DNS의 TTL은 짧게 (10초 권장)
안티패턴 3. 애플리케이션에서 DNS를 한 번만 해석한다
일부 언어/라이브러리는 부팅 시 DNS만 보고 캐싱한다.
이러면 TTL이 짧아도 의미가 없다.
매 호출마다 새로 해석하거나, 짧은 캐시를 명시적으로 켠다
안티패턴 4. Service Discovery를 외부 트래픽에 쓴다
.local 은 VPC 내부에서만 응답한다.
9. 한 줄로 정리
Service Discovery는 자주 바뀌는 컨테이너 IP를
이름 하나로 안정적으로 부를 수 있게 만든다
10. 이 장의 핵심 정리
- ECS Task는 IP가 자주 바뀌므로 내부 호출에 이름이 필요하다.
- Cloud Map은 Task를 자동으로 DNS에 등록해준다.
- ALB는 외부 트래픽, Service Discovery는 내부 호출이다.
- DNS TTL은 짧게, 클라이언트 캐시도 점검한다.
- 새 프로젝트는 Service Connect 도 검토할 가치가 있다.